package com.ruoyi.loan.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.loan.dto.UpdatePasswordDto;
import com.ruoyi.loan.dto.UserLoginDto;
import com.ruoyi.loan.dto.UserRegisterDto;
import com.ruoyi.loan.entity.User;
import com.ruoyi.loan.mapper.UserMapper;
import com.ruoyi.loan.service.AuthService;
import com.ruoyi.loan.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;

/**
 * @author coderFu
 * @create 2022/4/5
 */
@Service
@Slf4j
public class AuthServiceImpl implements AuthService {

    private static final String EMAIL_CODE = "emailCode";

    @Autowired
    private UserMapper userMapper;

    @Resource
    private HttpServletRequest request;

    @Resource
    private HttpServletResponse response;

    @Autowired
    private FileUtils fileUtils;

    /**
     * 设置过期时间 15分钟。
     */
    private static final int EXPIRE_TIME  = 15*60;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void register(UserRegisterDto userRegisterDto) {
        // 检查是否注册过
        User userObj = userMapper.selectOne(new QueryWrapper<User>().eq("id_card", userRegisterDto.getIdCard()));
        if (userObj != null){
            throw new RuntimeException("该身份已经注册");
        }

        // 校验手机号是否合法
        boolean flag = CheckPhoneUtils.checkPhone(userRegisterDto.getPhone());
        log.info("输入的手机号为："+userRegisterDto.getPhone());
        if (!flag){
            throw new RuntimeException("手机号格式不正确");
        }
        // 校验身份证是否合法
        boolean flagB = CheckIdentityCard.checkIdentityCard(userRegisterDto.getIdCard());
        log.info("输入的身份证号为："+userRegisterDto.getIdCard());
        if (! flagB){
            throw new RuntimeException("身份证号码不正确");
        }

        // 校验邮箱是否合法
        boolean flagE = CheckMailUtils.validEmail(userRegisterDto.getMail());
        log.info("输入的邮箱为："+userRegisterDto.getMail());
        if (! flagE){
            throw new RuntimeException("邮箱格式不正确");
        }

        // 检查密码长度是否满足要求
        boolean flagC = PasswordUtils.checkPasswordLength(userRegisterDto.getPassword());

        if (! flagC){
            throw new RuntimeException("密码长度不合规");
        }
        // 获取加密盐
        String encryptionSalt = PasswordUtils.getEncryptionSalt();
        // 对密码进行加密
        String encryptionPassword = PasswordUtils.getEncryptionPassword(userRegisterDto.getPassword(), encryptionSalt);

        User user = new User();
        BeanUtils.copyProperties(userRegisterDto,user);
        user.setSalt(encryptionSalt);
        user.setPassword(encryptionPassword);
        user.setUsername(userRegisterDto.getUsername());
        // 存储到数据库中
        userMapper.insert(user);
    }

    @Override
    public void login(UserLoginDto userLoginDto) {

        // 查看密码长度是否满足要求
        boolean flag = PasswordUtils.checkPasswordLength(userLoginDto.getPassword());
        if (! flag){
            throw new RuntimeException("密码长度不合规");
        }

        // 查询加密的盐信息
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("id_card", userLoginDto.getIdCard()));
        if (user == null){
            throw new RuntimeException("登录账户不存在");
        }
        user.setAvatarUrl(fileUtils.getShowFilePath(user.getAvatarUrl()));
        // 获取加密后的密码
        String password = user.getPassword();

        String encryptionPassword = PasswordUtils.getEncryptionPassword(userLoginDto.getPassword(), user.getSalt());

        if (password.equals(encryptionPassword)){
            // 成功登录
            HttpSession session = request.getSession();
            session.setAttribute(session.getId(),user);
            session.setMaxInactiveInterval(EXPIRE_TIME);
            response.setHeader("cookie",session.getId());
        }else{
            throw new RuntimeException("账号或密码有误");
        }

    }

    @Override
    public void checkMailCode(int mailCode) {
        // 从session中获取EmailCode
        HttpSession session = request.getSession();
        Object emailCode = session.getAttribute(EMAIL_CODE);
        if (emailCode != null && StringUtils.isNotEmpty(emailCode.toString())){
            if (Integer.parseInt(emailCode.toString()) != mailCode){
                throw new RuntimeException("验证码错误");
            }else{
                // 已经成功对比后，删除存储的二维码
                session.removeAttribute(EMAIL_CODE);
            }
        }else{
            throw new RuntimeException("验证码错误或验证码已过期");
        }
    }

    @Override
    public void sendMailCode(String idCard,String mail) {

        // 校验身份证号的合法性
        boolean flag = CheckIdentityCard.checkIdentityCard(idCard);
        if ( ! flag){
            throw  new RuntimeException("身份证号不合法");
        }
        // 校验身份证号是否存在
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("id_card", idCard));

        if (user == null){
            throw new RuntimeException("该用户不存在");
        }
        // 获取用户的邮箱信息
        String reallyMail = user.getMail();

        // 对比邮箱是否正确
        if (!reallyMail.equals(mail)){
            throw  new RuntimeException("身份证号和邮箱不匹配");
        }

        // 获取随机验证码
        int emailCode = RandomNumUtils.randomProduceSixNum();

        // 获取发送内容
        String text = MailUtils.getTEXT(emailCode);

        // 发送验证码
        MailUtils.sendEmail(mail,text,MailUtils.FIND_PASSWORD_CODE_TITLE);
        // 存储验证码到我们的session中
        HttpSession session = request.getSession();
        session.setAttribute(EMAIL_CODE,emailCode);
    }

    @Override
    public void updatePassword(UpdatePasswordDto updatePasswordDto) {
        // 校验验证码的正确性
        checkMailCode(updatePasswordDto.getCode());

        // 校验用户身份
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("id_card", updatePasswordDto.getIdCard()));

        if (user == null){
            throw new RuntimeException("该用户不存在");
        }

        // 检查密码是否合规
        boolean flagA = PasswordUtils.checkPasswordLength(updatePasswordDto.getPassword());

        if (! flagA){
            throw new RuntimeException("密码长度不符合要求");
        }

        // 获取加密的盐值
        String encryptionSalt = PasswordUtils.getEncryptionSalt();

        //进行密码加密
        String encryptionPassword = PasswordUtils.getEncryptionPassword(updatePasswordDto.getPassword(), encryptionSalt);
        user.setPassword(encryptionPassword);
        user.setSalt(encryptionSalt);
        //更新到数据库中
        int result = userMapper.update(user, new UpdateWrapper<User>().eq("id_card", user.getIdCard()));
        if (result < 1){
            throw new RuntimeException("密码重置失败，请重试");
        }
    }
}
